﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceProcess;


namespace CrmCustomInstallActions.Commands
{
    class HandleServiceCommand : GenericCrmSolutionCommand
    {

        private string serviceName = "";
        private string serviceCommand = "";

        internal override bool InitializeSpecificCommand()
        {
            try
            {
                serviceName = Config.SelectSingleNode("ServiceName").InnerText;
                serviceCommand = Config.SelectSingleNode("Command").InnerText.ToUpper();
                return true;
            }
            catch (Exception e)
            {
                Exceptions.Add("ConfigurationError", e.Message);
                WriteLog("Failed to read the service name and/or the service service start/stop command");
                return false;
            }

        }

        public override bool ExecuteCommand(CommandModes CommandMode)
        {
            try
            {
                ServiceController service = new ServiceController(serviceName);
                if (service == null)
                {
                    WriteLog("Failed to find the service '" + serviceName + "' on the local machine");
                    return false;
                }

                if (CommandMode == CommandModes.Rollback)
                {
                    // For this command we just swap the START/STOP parameter
                    if (serviceCommand == "START")
                    {
                        serviceCommand = "STOP";
                    }
                    else if (serviceCommand == "STOP")
                    {
                        serviceCommand = "START";
                    }
                }

                // Execute the START/STOP command

                if (serviceCommand == "STOP")
                {
                    WriteLog("Stopping the service '" + serviceName + "'");
                    ReportProgress(25, "Examining the service '" + serviceName + "'");
                    if (service.Status != ServiceControllerStatus.Running)
                    {
                        // Service may be stopped already
                        if (service.Status == ServiceControllerStatus.Stopped)
                        {
                            WriteLog("Service already stopped");
                            ReportProgress(100, "Service stopped");
                            return true;
                        }
                        else
                        {
                            WriteLog("The service '" + serviceName + "' is in the state of '" + service.Status.ToString() + "' and cannot be stopped");
                            return false;
                        }
                    }
                    else
                    {
                        if (service.CanStop)
                        {
                            ReportProgress(50, "Stopping the service '" + serviceName + "'");
                            service.Stop();
                            service.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 60));
                            if (service.Status == ServiceControllerStatus.Stopped)
                            {
                                ReportProgress(100, "Service stopped");
                                WriteLog("Service stopped");
                                return true;
                            }
                            else
                            {
                                WriteLog("A Stop command was issued but the service is still in the state '" + service.Status.ToString() + "' after 60 seconds");
                                return false;
                            }
                        }
                        else
                        {
                            WriteLog("The service is running but cannot be stopped by the Solution installer. Stop the service manually and run the Crm Solution installer again");
                            return false;
                        }
                    }
                }
                else if (serviceCommand == "START")
                {
                    WriteLog("Starting the service '" + serviceName + "'");
                    ReportProgress(25, "Examining the service '" + serviceName + "'");
                    if (service.Status != ServiceControllerStatus.Stopped)
                    {
                        // Service may be started already
                        if (service.Status == ServiceControllerStatus.Running)
                        {
                            WriteLog("Service already running");
                            ReportProgress(100, "Service started");
                            return true;
                        }
                        else
                        {
                            WriteLog("The service '" + serviceName + "' is in the state of '" + service.Status.ToString() + "' and cannot be stopped");
                            return false;
                        }
                    }
                    else
                    {
                        ReportProgress(50, "Starting the service '" + serviceName + "'");
                        service.Start();
                        service.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 60));
                        if (service.Status == ServiceControllerStatus.Running)
                        {
                            ReportProgress(100, "Service started");
                            WriteLog("Service started");
                            return true;
                        }
                        else
                        {
                            WriteLog("A start command was issued but the service is still in the state '" + service.Status.ToString() + "' after 60 seconds");
                            return false;
                        }
                    }
                }
                else
                {
                    WriteLog("The command '" + serviceCommand + "' is not valid. Only START/STOP are valid service commands");
                    return false;
                }
            }
            catch (Exception e)
            {
                Exceptions.Add(serviceName,e.Message);
                WriteLog("An error occured while executing the '" + serviceCommand + "' command on the service '" + serviceName + "'");
                return false;
            }
        }
        public override bool SupportsUninstall
        {
            get { return true; }
        }

        public override bool SupportsUserInterface
        {
            get { return false; }
        }
    }
}
